package com.cx.controller;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cx.entity.LolBattleChampionEntity;
import com.cx.entity.LolHeaderJoinTeamEntity;
import com.cx.entity.LolTeamJoinChampionEntity;
import com.cx.po.LolBattleChampionPo;
import com.cx.po.LolBattleHeaderPo;
import com.cx.po.LolBattleTeamPo;
import com.cx.service.LolBattleChampionService;
import com.cx.service.LolBattleHeaderService;
import com.cx.service.LolBattleTeamService;
import com.cx.vo.LolBattleChampionVo;
import com.cx.vo.LolBattleHeaderVo;
import com.cx.vo.LolBattleTeamVo;
import com.cx.vo.ResultVo;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * mongoDB课题控制类
 *
 * @author 残星
 */
@RestController
@RequestMapping(value = "mongoSubjectController")
@CrossOrigin
public class MongoSubjectController {
    @Resource(name = "mongoTemplate")
    private MongoTemplate mongoTemplate;
    @Resource(name = "lolBattleHeaderServiceImpl")
    private LolBattleHeaderService lolBattleHeaderService;
    @Resource(name = "lolBattleTeamServiceImpl")
    private LolBattleTeamService lolBattleTeamService;
    @Resource(name = "lolBattleChampionServiceImpl")
    private LolBattleChampionService lolBattleChampionService;

    /**
     * 从数据库查询对局信息
     *
     * @param currentPage 当前页数，默认1
     * @param pageSize    每页大小，默认10
     * @return 返回结果封装类
     */
    @GetMapping(value = "getLolBattleHeaderPage")
    public ResultVo<Page<LolBattleHeaderPo>> getLolBattleHeaderPage(
            @RequestParam(value = "page", defaultValue = "1") Integer currentPage,
            @RequestParam(value = "limit", defaultValue = "5") Integer pageSize) {
        ResultVo<Page<LolBattleHeaderPo>> resultVo = new ResultVo<>();
        Page<LolBattleHeaderPo> page = new Page<>(currentPage, pageSize);
        try {
            Page<LolBattleHeaderPo> lolBattleHeaderPage = lolBattleHeaderService.findLolHeaderPage(page);
            resultVo.setSuccess(true);
            resultVo.result("0", "操作成功！", lolBattleHeaderPage);
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "操作失败！");
        }
        return resultVo;
    }

    /**
     * 从数据库查询对局队伍信息
     *
     * @param currentPage 当前页数，默认1
     * @param pageSize    每页大小，默认10
     * @return 返回结果封装类
     */
    @GetMapping(value = "getLolBattleTeamPage")
    public ResultVo<Page<LolBattleTeamPo>> getLolBattleTeamPage(
            @RequestParam(value = "page", defaultValue = "1") Integer currentPage,
            @RequestParam(value = "limit", defaultValue = "5") Integer pageSize) {
        ResultVo<Page<LolBattleTeamPo>> resultVo = new ResultVo<>();
        Page<LolBattleTeamPo> page = new Page<>(currentPage, pageSize);
        try {
            Page<LolBattleTeamPo> lolTeamPage = lolBattleTeamService.findLolTeamPage(page);
            resultVo.setSuccess(true);
            resultVo.result("0", "操作成功！", lolTeamPage);
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "操作失败！");
        }
        return resultVo;
    }

    /**
     * 从数据库查询对局英雄信息
     *
     * @param currentPage 当前页数，默认1
     * @param pageSize    每页大小，默认10
     * @return 返回结果封装类
     */
    @GetMapping(value = "getLolBattleChampionPage")
    public ResultVo<Page<LolBattleChampionPo>> getLolBattleChampionPage(
            @RequestParam(value = "page", defaultValue = "1") Integer currentPage,
            @RequestParam(value = "limit", defaultValue = "5") Integer pageSize) {
        ResultVo<Page<LolBattleChampionPo>> resultVo = new ResultVo<>();
        Page<LolBattleChampionPo> page = new Page<>(currentPage, pageSize);
        try {
            Page<LolBattleChampionPo> lolChampionPage = lolBattleChampionService.findLolChampionPage(page);
            resultVo.setSuccess(true);
            resultVo.result("0", "操作成功！", lolChampionPage);
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "操作失败！");
        }
        return resultVo;
    }

    /**
     * 从MySQL初始化数据到MongoDB
     *
     * @return 返回结果封装类
     */
    @GetMapping(value = "initCollections")
    public ResultVo<Object> initCollections() {
        ResultVo<Object> resultVo = new ResultVo<>();
        mongoTemplate.dropCollection(LolBattleHeaderPo.class);
        mongoTemplate.dropCollection(LolBattleTeamPo.class);
        mongoTemplate.dropCollection(LolBattleChampionPo.class);
        ResultVo<Page<LolBattleHeaderPo>> lolBattleHeaderPage = this.getLolBattleHeaderPage(1, 5);
        ResultVo<Page<LolBattleTeamPo>> lolBattleTeamPage = this.getLolBattleTeamPage(1, 999);
        ResultVo<Page<LolBattleChampionPo>> lolBattleChampionPage = this.getLolBattleChampionPage(1, 999);
        try {
            mongoTemplate.insertAll(lolBattleHeaderPage.getData().getRecords());
            mongoTemplate.insertAll(lolBattleTeamPage.getData().getRecords());
            mongoTemplate.insertAll(lolBattleChampionPage.getData().getRecords());
            resultVo.setSuccess(true);
            resultVo.result("0", "初始化数据到MongoDB成功");
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "初始化数据失败");
        }
        return resultVo;
    }

    /**
     * 从MongoDB联表查询对局记录、队伍、英雄数据
     */
    @GetMapping(value = "getLolBattleFromMongoDb")
    public ResultVo<List<LolHeaderJoinTeamEntity>> getLolBattleFromMongoDb() {
        ResultVo<List<LolHeaderJoinTeamEntity>> resultVo = new ResultVo<>();
        LookupOperation headerJoinTeam = LookupOperation.newLookup()
                //关联从表名
                .from("lol_battle_team")
                //主表关联字段
                .localField("gameId")
                //从表关联的字段
                .foreignField("gameId")
                //查询结果名
                .as("lolBattleTeamList");
        LookupOperation teamJoinChampion = LookupOperation.newLookup()
                //关联从表名
                .from("lol_battle_champion")
                //主表关联字段
                .localField("gameId")
                //从表关联的字段
                .foreignField("gameId")
                //查询结果名
                .as("lolBattleChampionList");
        Aggregation headerJoinTeamJoinChampionAgg = Aggregation.newAggregation(headerJoinTeam, teamJoinChampion);
        try {
            AggregationResults<LolHeaderJoinTeamEntity> headerJoinTeamEntityAggResults =
                    mongoTemplate.aggregate(headerJoinTeamJoinChampionAgg, LolBattleHeaderPo.class, LolHeaderJoinTeamEntity.class);
            List<LolHeaderJoinTeamEntity> mappedResults = headerJoinTeamEntityAggResults.getMappedResults();
            // 这里需要将对局英雄信息，根据队伍（蓝色方/红色方）拆分后，再组装到对应的队伍信息下
            List<LolHeaderJoinTeamEntity> resultList = mappedResults.stream().peek(lolHeaderJoinTeamEntity -> {
                List<LolTeamJoinChampionEntity> lolBattleTeamList = lolHeaderJoinTeamEntity.getLolBattleTeamList();
                // 判断是否已删除
                if (CollUtil.isEmpty(lolBattleTeamList)) {
                    return;
                }
                List<LolBattleChampionEntity> blue = new ArrayList<>();
                List<LolBattleChampionEntity> red = new ArrayList<>();
                for (LolTeamJoinChampionEntity lolTeamJoinChampionEntity : lolBattleTeamList) {
                    if ("红色方".equals(lolTeamJoinChampionEntity.getTeam())) {
                        red = lolTeamJoinChampionEntity.getLolBattleChampionList();
                    } else {
                        blue = lolTeamJoinChampionEntity.getLolBattleChampionList();
                    }
                }
                List<LolBattleChampionEntity> lolBattleChampionList = lolHeaderJoinTeamEntity.getLolBattleChampionList();
                for (LolBattleChampionEntity lolBattleChampionEntity : lolBattleChampionList) {
                    // 判断如果是红色方则加入red，否则加入blue
                    if ("红色方".equals(lolBattleChampionEntity.getTeam())) {
                        red.add(lolBattleChampionEntity);
                    } else {
                        blue.add(lolBattleChampionEntity);
                    }
                }
                lolBattleChampionList.clear();
            }).collect(Collectors.toList());
            resultVo.setSuccess(true);
            resultVo.result("0", "操作成功！", resultList);
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("0", "操作失败！");
        }
        return resultVo;
    }

    /**
     * 插入一条对局记录数据
     *
     * @param request 报文数据 {@link LolBattleHeaderVo}
     * @return 返回结果封装类
     */
    @PostMapping(value = "insertLolBattleHeaderDocument")
    public ResultVo<Object> insertLolBattleHeaderDocument(@RequestBody String request) {
        LolBattleHeaderVo lolBattleHeaderVo = JSONObject.parseObject(request, LolBattleHeaderVo.class);
        return lolBattleHeaderService.insertLolBattleHeaderDocument(lolBattleHeaderVo);
    }

    /**
     * 修改一条对局记录数据
     *
     * @param request 报文数据 {@link LolBattleHeaderVo}
     * @return 返回结果封装类
     */
    @PostMapping(value = "updateLolBattleHeaderDocument")
    public ResultVo<Object> updateLolBattleHeaderDocument(@RequestBody String request) {
        LolBattleHeaderVo lolBattleHeaderVo = JSONObject.parseObject(request, LolBattleHeaderVo.class);
        return lolBattleHeaderService.updateLolBattleHeaderDocument(lolBattleHeaderVo);
    }

    /**
     * 修改一条对局队伍数据
     *
     * @param request 报文数据 {@link LolBattleTeamVo}
     * @return 返回结果封装类
     */
    @PostMapping(value = "updateLolBattleTeamDocument")
    public ResultVo<Object> updateLolBattleTeamDocument(@RequestBody String request) {
        LolBattleTeamVo lolBattleTeamVo = JSONObject.parseObject(request, LolBattleTeamVo.class);
        return lolBattleTeamService.updateLolBattleTeamDocument(lolBattleTeamVo);
    }

    /**
     * 修改一条对局英雄数据
     *
     * @param request 报文数据 {@link LolBattleChampionVo}
     * @return 返回结果封装类
     */
    @PostMapping(value = "updateLolBattleChampionDocument")
    public ResultVo<Object> updateLolBattleChampionDocument(@RequestBody String request) {
        LolBattleChampionVo lolBattleChampionVo = JSONObject.parseObject(request, LolBattleChampionVo.class);
        return lolBattleChampionService.updateLolBattleChampionDocument(lolBattleChampionVo);
    }

    /**
     * 删除对局记录数据
     *
     * @param gameId 待删除的对局ID
     * @return 返回结果封装类
     */
    @PostMapping(value = "deleteLolBattleHeader")
    public ResultVo<Object> deleteLolBattleHeader(@RequestParam Long gameId) {
        ResultVo<Object> resultVo = new ResultVo<>();
        try {
            lolBattleHeaderService.deleteLolBattleHeader(gameId);
            lolBattleTeamService.deleteLolBattleTeam(gameId);
            lolBattleChampionService.deleteLolBattleChampion(gameId);
            resultVo.setSuccess(true);
            resultVo.result("0", "批量删除成功！");
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "批量删除失败！");
        }
        return resultVo;
    }

    /**
     * 删除对局队伍数据
     *
     * @param gameId 待删除的对局ID
     * @param id     待删除的MongoDB ID
     * @return 返回结果封装类
     */
    @PostMapping(value = "deleteLolBattleTeam")
    public ResultVo<Object> deleteLolBattleTeam(@RequestParam Long gameId, @RequestParam String id, @RequestParam String team) {
        ResultVo<Object> resultVo = new ResultVo<>();
        try {
            lolBattleTeamService.deleteLolBattleTeam(gameId, id);
            lolBattleChampionService.deleteLolBattleChampionByTeam(gameId, team);
            resultVo.setSuccess(true);
            resultVo.result("0", "批量删除成功！");
        } catch (Exception e) {
            e.printStackTrace();
            resultVo.result("500", "批量删除失败！");
        }
        return resultVo;
    }

    /**
     * 删除对局英雄数据
     *
     * @param gameId 待删除的对局ID
     * @param id     待删除的MongoDB ID
     * @return 返回结果封装类
     */
    @PostMapping(value = "deleteLolBattleChampion")
    public ResultVo<Object> deleteLolBattleChampion(@RequestParam Long gameId, @RequestParam String id) {
        return lolBattleChampionService.deleteLolBattleChampion(gameId, id);
    }
}
